/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package fr.adama.service;

import com.lowagie.text.Document;
import com.lowagie.text.DocumentException;
import com.lowagie.text.pdf.PdfCopy;
import com.lowagie.text.pdf.PdfReader;
import fr.adama.bulletin.CalculBulletin;
import fr.adama.constante.Constante;
import fr.adama.dto.BulletinPaieDTO;
import fr.adama.dto.ContratDTO;
import fr.adama.dto.CumulsDTO;
import fr.adama.dto.LigneHoraireDTO;
import fr.adama.dto.ModelePaieDTO;
import fr.adama.dto.notModel.SearchBulletin;
import fr.adama.entite.BulletinPaie;
import fr.adama.entite.Contrat;
import fr.adama.entite.modele.ModelePaie;
import fr.adama.entite.typePerso.EtatBulletin;
import fr.adama.exception.ArchiveException;
import fr.adama.exception.BulletinException;
import fr.adama.exception.BulletinFileNotFoundException;
import fr.adama.file.ExportFile;
import fr.adama.repository.BulletinPaieRepository;
import fr.adama.util.AdamaMarshaller;
import fr.adama.util.ZipUtil;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedList;
import java.util.List;
import java.util.logging.Level;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 *
 * @author mini-john
 */
@Service
@Transactional
public class BulletinPaieService extends CrudService {

    private static final Logger logger = LoggerFactory.getLogger(BulletinPaieService.class);
    @Autowired
    BulletinPaieRepository bulletinPaieRepository;
    @Autowired
    ModeleBulletinPaieService modeleBulletinPaieService;
    @Autowired
    ContratService contratService;
    @Autowired
    ExportFile ExportFile;
    @Autowired
    AdamaMarshaller adamaMarshaller;

    @Transactional(rollbackFor = BulletinException.class)
    public BulletinPaieDTO addBulletinPaie(BulletinPaieDTO bulletin) throws BulletinException {
        ModelePaieDTO modelPaie = modeleBulletinPaieService.getById(bulletin.getModelPaie().getId(), ModelePaie.class, ModelePaieDTO.class);
        ContratDTO contrat = contratService.getById(bulletin.getContrat().getId(), Contrat.class, ContratDTO.class);

        bulletin.setEtatBulletin(EtatBulletin.saisi);
        bulletin = CalculBulletin.calculBulletin(bulletin, modelPaie, contrat);
        CumulsDTO cumuls = bulletinPaieRepository.getCumuls(bulletin);

        String numero = contrat.getAdherent().getId() + "" + contrat.getEmploye().getId() + "" + bulletin.getAnnee() + "" + bulletin.getMois() + "";
        bulletin.setNumero(numero);
        bulletin = ExportFile.exportBulelletinPaie(bulletin, contrat, modelPaie, cumuls);

        bulletin = super.merge(bulletin, BulletinPaie.class);

        return bulletin;
    }

    @Transactional(rollbackFor = BulletinException.class)
    public BulletinPaieDTO updateBulletinPaie(BulletinPaieDTO bulletin) throws BulletinException {

        ModelePaieDTO modelPaie = modeleBulletinPaieService.getById(bulletin.getModelPaie().getId(), ModelePaie.class, ModelePaieDTO.class);
        ContratDTO contrat = contratService.getById(bulletin.getContrat().getId(), Contrat.class, ContratDTO.class);

        bulletin.setEtatBulletin(EtatBulletin.saisi);
        bulletin = CalculBulletin.calculBulletin(bulletin, modelPaie, contrat);
        CumulsDTO cumuls = bulletinPaieRepository.getCumuls(bulletin);

        bulletin = ExportFile.exportBulelletinPaie(bulletin, contrat, modelPaie, cumuls);
        bulletin.setEtatBulletin(EtatBulletin.saisi);
        bulletin = super.merge(bulletin, BulletinPaie.class);
        return bulletin;

    }

    public CumulsDTO getCumuls(BulletinPaieDTO bulletin) {
        return bulletinPaieRepository.getCumuls(bulletin);
    }

    public List<BulletinPaieDTO> searchBulletin(SearchBulletin searchBulletin) {
        List<BulletinPaie> listBulletin = bulletinPaieRepository.searchBulletin(searchBulletin);
        List<BulletinPaieDTO> result = new ArrayList<>();

        for (BulletinPaie bulletin : listBulletin) {
            BulletinPaieDTO dozerResult = mapperDozer.map(bulletin, BulletinPaieDTO.class);
            result.add(dozerResult);
        }
        return result;
    }

    @Transactional(rollbackFor = {BulletinFileNotFoundException.class, BulletinException.class, ArchiveException.class})
    public File getFileAllBulletinForPrint(Date periode) throws ArchiveException {

        try {
            File file = null;
            file = File.createTempFile("allBulletin" + periode.toString(), ".pdf");
            Document document = new Document();

            PdfCopy copy = new PdfCopy(document, new FileOutputStream(file));
            document.open();
            List<BulletinPaie> list = bulletinPaieRepository.getAllBulletinForPeriode(periode);
            int n;
            for (BulletinPaie bulletin : list) {
                File tmpFile = ZipUtil.getBulletinPDFFromZip(new File(bulletin.getPathToPdf()));
                PdfReader reader = new PdfReader(tmpFile.getAbsolutePath());
                n = reader.getNumberOfPages();
                for (int i = 0; i < Constante.nbBulletinToPrint; i++) {
                    for (int page = 0; page < n;) {
                        copy.addPage(copy.getImportedPage(reader, ++page));
                    }
                }
                copy.freeReader(reader);
                reader.close();
                bulletin.setEtatBulletin(EtatBulletin.imprime);
                bulletinPaieRepository.update(bulletin);
                tmpFile.delete();
            }
            document.close();
            return file;
        } catch (DocumentException | IOException ex) {
            logger.error("Erreur lors de la génération du pdf des bulletins de paies ", ex);
            throw new BulletinException(ex);
        }

    }

    @Override
    public <T> T getById(Long id, Class entity, Class entityDTO) {
        try {
            BulletinPaieDTO bulletin = super.getById(id, entity, entityDTO);
            File ligneHoraire = ZipUtil.getLigneHoraireXMLFromZip(new File(bulletin.getPathToPdf()));
            LinkedList<LigneHoraireDTO> ligneHoraireList;
            ligneHoraireList = (LinkedList<LigneHoraireDTO>) adamaMarshaller.unmarshal(ligneHoraire);
            bulletin.setLigneHoraire(ligneHoraireList);
            return (T) bulletin;
        } catch (IOException ex) {
            logger.error("Erreur lors de la récupération des lignes horaires ", ex);
            throw new BulletinException(ex);
        } catch (ArchiveException ex) {
            logger.error("Erreur lors de la récupération des lignes horaires ", ex);
            throw new BulletinException(ex);
        }
        
    }

}
